Implemented height-for-width geometry management for menus
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Wed, 18 Aug 2010 23:42:02 +0000 (19:42 -0400)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Thu, 19 Aug 2010 00:01:28 +0000 (20:01 -0400)
Now GtkMenu/GtkMenuItem request/allocate in height-for-width
manner... to reduce the height of the menu one must explicitly
set the requested minimum width of the menu to a greater value
(using gtk_widget_set_size_request()).

gtk/gtkmenu.c
gtk/gtkmenuitem.c

index 39c83f2e8b0111a6007bd22ff1c2d963df76d794..03aff5509a6da56e373347002ca99b7d9c32a74f 100644 (file)
@@ -41,6 +41,7 @@
 #include "gtkhbox.h"
 #include "gtkvscrollbar.h"
 #include "gtksettings.h"
+#include "gtksizerequest.h"
 #include "gtkprivate.h"
 #include "gtkintl.h"
 
@@ -79,6 +80,7 @@ struct _GtkMenuPrivate
   /* info used for the table */
   guint *heights;
   gint heights_length;
+  gint requested_height;
 
   gint monitor_num;
 
@@ -86,6 +88,8 @@ struct _GtkMenuPrivate
   gint n_rows;
   gint n_columns;
 
+  guint accel_size;
+
   gchar *title;
 
   /* Arrow states */
@@ -169,8 +173,6 @@ static void     gtk_menu_get_child_property(GtkContainer     *container,
 static void     gtk_menu_destroy           (GtkObject        *object);
 static void     gtk_menu_realize           (GtkWidget        *widget);
 static void     gtk_menu_unrealize         (GtkWidget        *widget);
-static void     gtk_menu_size_request      (GtkWidget        *widget,
-                                           GtkRequisition   *requisition);
 static void     gtk_menu_size_allocate     (GtkWidget        *widget,
                                            GtkAllocation    *allocation);
 static void     gtk_menu_paint             (GtkWidget        *widget,
@@ -258,6 +260,19 @@ static gboolean gtk_menu_real_can_activate_accel (GtkWidget *widget,
 static void _gtk_menu_refresh_accel_paths (GtkMenu *menu,
                                           gboolean group_changed);
 
+static void gtk_menu_size_request_init          (GtkSizeRequestIface *iface);
+static void gtk_menu_get_width                  (GtkSizeRequest      *widget,
+                                                gint                *minimum_size,
+                                                gint                *natural_size);
+static void gtk_menu_get_height                 (GtkSizeRequest      *widget,
+                                                gint                *minimum_size,
+                                                gint                *natural_size);
+static void gtk_menu_get_height_for_width       (GtkSizeRequest      *widget,
+                                                gint                 for_size,
+                                                gint                *minimum_size,
+                                                gint                *natural_size);
+
+
 static const gchar attach_data_key[] = "gtk-menu-attach-data";
 
 static guint menu_signals[LAST_SIGNAL] = { 0 };
@@ -268,7 +283,9 @@ gtk_menu_get_private (GtkMenu *menu)
   return G_TYPE_INSTANCE_GET_PRIVATE (menu, GTK_TYPE_MENU, GtkMenuPrivate);
 }
 
-G_DEFINE_TYPE (GtkMenu, gtk_menu, GTK_TYPE_MENU_SHELL)
+G_DEFINE_TYPE_WITH_CODE (GtkMenu, gtk_menu, GTK_TYPE_MENU_SHELL,
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST,
+                                               gtk_menu_size_request_init))
 
 static void
 menu_queue_resize (GtkMenu *menu)
@@ -459,7 +476,6 @@ gtk_menu_class_init (GtkMenuClass *class)
   
   widget_class->realize = gtk_menu_realize;
   widget_class->unrealize = gtk_menu_unrealize;
-  widget_class->size_request = gtk_menu_size_request;
   widget_class->size_allocate = gtk_menu_size_allocate;
   widget_class->show = gtk_menu_show;
   widget_class->expose_event = gtk_menu_expose;
@@ -1625,7 +1641,7 @@ gtk_menu_popup_for_device (GtkMenu             *menu,
     GtkRequisition tmp_request;
     GtkAllocation tmp_allocation = { 0, };
 
-    gtk_widget_size_request (menu->toplevel, &tmp_request);
+    gtk_size_request_get_size (GTK_SIZE_REQUEST (menu->toplevel), NULL, &tmp_request);
     
     tmp_allocation.width = tmp_request.width;
     tmp_allocation.height = tmp_request.height;
@@ -2042,10 +2058,13 @@ gtk_menu_set_tearoff_hints (GtkMenu *menu,
                            gint     width)
 {
   GdkGeometry geometry_hints;
-  
+  GtkMenuPrivate *priv;
+
   if (!menu->tearoff_window)
     return;
 
+  priv = gtk_menu_get_private (menu);
+
   if (gtk_widget_get_visible (menu->tearoff_scrollbar))
     {
       gtk_widget_size_request (menu->tearoff_scrollbar, NULL);
@@ -2056,7 +2075,7 @@ gtk_menu_set_tearoff_hints (GtkMenu *menu,
   geometry_hints.max_width = width;
     
   geometry_hints.min_height = 0;
-  geometry_hints.max_height = GTK_WIDGET (menu)->requisition.height;
+  geometry_hints.max_height = priv->requested_height;
 
   gtk_window_set_geometry_hints (GTK_WINDOW (menu->tearoff_window),
                                 NULL,
@@ -2122,10 +2141,13 @@ void
 gtk_menu_set_tearoff_state (GtkMenu  *menu,
                            gboolean  torn_off)
 {
-  gint width, height;
+  gint            width, height;
+  GtkMenuPrivate *priv;
   
   g_return_if_fail (GTK_IS_MENU (menu));
 
+  priv = gtk_menu_get_private (menu);
+
   if (menu->torn_off != torn_off)
     {
       menu->torn_off = torn_off;
@@ -2170,7 +2192,7 @@ gtk_menu_set_tearoff_state (GtkMenu  *menu,
              menu->tearoff_adjustment =
                GTK_ADJUSTMENT (gtk_adjustment_new (0,
                                                    0,
-                                                   GTK_WIDGET (menu)->requisition.height,
+                                                   priv->requested_height,
                                                    MENU_SCROLL_STEP2,
                                                    height/2,
                                                    height));
@@ -2371,6 +2393,7 @@ gtk_menu_realize (GtkWidget *widget)
   gint attributes_mask;
   gint border_width;
   GtkMenu *menu;
+  GtkMenuPrivate *priv;
   GtkWidget *child;
   GList *children;
   guint vertical_padding;
@@ -2380,7 +2403,8 @@ gtk_menu_realize (GtkWidget *widget)
   g_return_if_fail (GTK_IS_MENU (widget));
 
   menu = GTK_MENU (widget);
-  
+  priv = gtk_menu_get_private (menu);
+
   gtk_widget_set_realized (widget, TRUE);
   
   attributes.window_type = GDK_WINDOW_CHILD;
@@ -2424,7 +2448,7 @@ gtk_menu_realize (GtkWidget *widget)
   attributes.x = 0;
   attributes.y = 0;
   attributes.width = MAX (1, widget->allocation.width - (border_width + widget->style->xthickness + horizontal_padding) * 2);
-  attributes.height = MAX (1, widget->requisition.height - (border_width + widget->style->ythickness + vertical_padding) * 2);
+  attributes.height = MAX (1, priv->requested_height - (border_width + widget->style->ythickness + vertical_padding) * 2);
   
   menu->bin_window = gdk_window_new (menu->view_window, &attributes, attributes_mask);
   gdk_window_set_user_data (menu->bin_window, menu);
@@ -2525,118 +2549,82 @@ gtk_menu_unrealize (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_menu_parent_class)->unrealize (widget);
 }
 
-static void
-gtk_menu_size_request (GtkWidget      *widget,
-                      GtkRequisition *requisition)
+
+static gint
+calculate_line_heights (GtkMenu *menu,
+                       gint     for_width,
+                       guint  **ret_min_heights,
+                       guint  **ret_nat_heights)
 {
-  gint i;
-  GtkMenu *menu;
-  GtkMenuShell *menu_shell;
-  GtkWidget *child;
-  GList *children;
-  guint max_toggle_size;
-  guint max_accel_width;
-  guint vertical_padding;
-  guint horizontal_padding;
-  guint border_width;
-  GtkRequisition child_requisition;
+  GtkMenuShell   *menu_shell;
   GtkMenuPrivate *priv;
+  GtkWidget      *child, *widget;
+  GList          *children;
+  guint           horizontal_padding;
+  guint           border_width;
+  guint           n_columns;
+  gint            n_heights;
+  guint          *min_heights;
+  guint          *nat_heights;
+  gint            avail_width;
+    
+  widget       = GTK_WIDGET (menu);
+  menu_shell   = GTK_MENU_SHELL (widget);
+  priv         = gtk_menu_get_private (menu);
   
-  g_return_if_fail (GTK_IS_MENU (widget));
-  g_return_if_fail (requisition != NULL);
-  
-  menu = GTK_MENU (widget);
-  menu_shell = GTK_MENU_SHELL (widget);
-  priv = gtk_menu_get_private (menu);
-  
-  requisition->width = 0;
-  requisition->height = 0;
-  
-  max_toggle_size = 0;
-  max_accel_width = 0;
-  
-  g_free (priv->heights);
-  priv->heights = g_new0 (guint, gtk_menu_get_n_rows (menu));
-  priv->heights_length = gtk_menu_get_n_rows (menu);
+  min_heights  = g_new0 (guint, gtk_menu_get_n_rows (menu));
+  nat_heights  = g_new0 (guint, gtk_menu_get_n_rows (menu));
+  n_heights    = gtk_menu_get_n_rows (menu);
+  n_columns    = gtk_menu_get_n_columns (menu);
+  avail_width  = for_width - (2 * menu->toggle_size + priv->accel_size) * n_columns;
 
-  children = menu_shell->children;
-  while (children)
+  gtk_widget_style_get (GTK_WIDGET (menu),
+                        "horizontal-padding", &horizontal_padding,
+                       NULL);
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (menu));
+  avail_width -= (border_width + horizontal_padding + widget->style->xthickness) * 2;
+
+  for (children = menu_shell->children; children; children = children->next)
     {
       gint part;
       gint toggle_size;
       gint l, r, t, b;
+      gint child_min, child_nat;
 
       child = children->data;
-      children = children->next;
       
       if (! gtk_widget_get_visible (child))
         continue;
 
       get_effective_child_attach (child, &l, &r, &t, &b);
 
-      /* It's important to size_request the child
-       * before doing the toggle size request, in
-       * case the toggle size request depends on the size
-       * request of a child of the child (e.g. for ImageMenuItem)
-       */
-
-       GTK_MENU_ITEM (child)->show_submenu_indicator = TRUE;
-       gtk_widget_size_request (child, &child_requisition);
+      part = avail_width / (r - l);
 
-       gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size);
-       max_toggle_size = MAX (max_toggle_size, toggle_size);
-       max_accel_width = MAX (max_accel_width,
-                              GTK_MENU_ITEM (child)->accelerator_width);
+      gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (child), part,
+                                            &child_min, &child_nat);
 
-       part = child_requisition.width / (r - l);
-       requisition->width = MAX (requisition->width, part);
-
-       part = MAX (child_requisition.height, toggle_size) / (b - t);
-       priv->heights[t] = MAX (priv->heights[t], part);
-    }
-
-  /* If the menu doesn't include any images or check items
-   * reserve the space so that all menus are consistent.
-   * We only do this for 'ordinary' menus, not for combobox
-   * menus or multi-column menus
-   */
-  if (max_toggle_size == 0 && 
-      gtk_menu_get_n_columns (menu) == 1 &&
-      !priv->no_toggle_size)
-    {
-      guint toggle_spacing;
-      guint indicator_size;
+      gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size);
+      
+      part = MAX (child_min, toggle_size) / (b - t);
+      min_heights[t] = MAX (min_heights[t], part);
 
-      gtk_style_get (widget->style,
-                     GTK_TYPE_CHECK_MENU_ITEM,
-                     "toggle-spacing", &toggle_spacing,
-                     "indicator-size", &indicator_size,
-                     NULL);
+      part = MAX (child_nat, toggle_size) / (b - t);
+      nat_heights[t] = MAX (nat_heights[t], part);
 
-      max_toggle_size = indicator_size + toggle_spacing;
     }
 
-  for (i = 0; i < gtk_menu_get_n_rows (menu); i++)
-    requisition->height += priv->heights[i];
-
-  requisition->width += 2 * max_toggle_size + max_accel_width;
-  requisition->width *= gtk_menu_get_n_columns (menu);
-
-  gtk_widget_style_get (GTK_WIDGET (menu),
-                       "vertical-padding", &vertical_padding,
-                        "horizontal-padding", &horizontal_padding,
-                       NULL);
+  if (ret_min_heights)
+    *ret_min_heights = min_heights;
+  else
+    g_free (min_heights);
 
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (menu));
-  requisition->width += (border_width + horizontal_padding + widget->style->xthickness) * 2;
-  requisition->height += (border_width + vertical_padding + widget->style->ythickness) * 2;
+  if (ret_nat_heights)
+    *ret_nat_heights = nat_heights;
+  else
+    g_free (nat_heights);
   
-  menu->toggle_size = max_toggle_size;
-
-  /* Don't resize the tearoff if it is not active, because it won't redraw (it is only a background pixmap).
-   */
-  if (menu->tearoff_active)
-    gtk_menu_set_tearoff_hints (menu, requisition->width);
+  return n_heights;
 }
 
 static void
@@ -2647,10 +2635,9 @@ gtk_menu_size_allocate (GtkWidget     *widget,
   GtkMenuShell *menu_shell;
   GtkWidget *child;
   GtkAllocation child_allocation;
-  GtkRequisition child_requisition;
   GtkMenuPrivate *priv;
   GList *children;
-  gint x, y;
+  gint x, y, i;
   gint width, height;
   guint border_width;
   guint vertical_padding;
@@ -2664,23 +2651,31 @@ gtk_menu_size_allocate (GtkWidget     *widget,
   priv = gtk_menu_get_private (menu);
 
   widget->allocation = *allocation;
-  gtk_widget_get_child_requisition (GTK_WIDGET (menu), &child_requisition);
 
   gtk_widget_style_get (GTK_WIDGET (menu),
                        "vertical-padding", &vertical_padding,
                         "horizontal-padding", &horizontal_padding,
                        NULL);
-
   border_width = gtk_container_get_border_width (GTK_CONTAINER (menu));
+
+  g_free (priv->heights);
+  priv->heights_length = 
+    calculate_line_heights (menu,
+                           allocation->width,
+                           &priv->heights,
+                           NULL);
+
+  /* refresh our cached height request */
+  priv->requested_height = (border_width + vertical_padding + GTK_WIDGET (widget)->style->ythickness) * 2;
+  for (i = 0; i < priv->heights_length; i++)
+    priv->requested_height += priv->heights[i];
+
   x = border_width + widget->style->xthickness + horizontal_padding;
   y = border_width + widget->style->ythickness + vertical_padding;
 
   width = MAX (1, allocation->width - x * 2);
   height = MAX (1, allocation->height - y * 2);
 
-  child_requisition.width -= x * 2;
-  child_requisition.height -= y * 2;
-
   if (menu_shell->active)
     gtk_menu_scroll_to (menu, menu->scroll_offset);
 
@@ -2769,7 +2764,7 @@ gtk_menu_size_allocate (GtkWidget     *widget,
 
       if (menu->tearoff_active)
        {
-         if (allocation->height >= widget->requisition.height)
+         if (allocation->height >= priv->requested_height)
            {
              if (gtk_widget_get_visible (menu->tearoff_scrollbar))
                {
@@ -2781,7 +2776,7 @@ gtk_menu_size_allocate (GtkWidget     *widget,
            }
          else
            {
-             menu->tearoff_adjustment->upper = widget->requisition.height;
+             menu->tearoff_adjustment->upper = priv->requested_height;
              menu->tearoff_adjustment->page_size = allocation->height;
              
              if (menu->tearoff_adjustment->value + menu->tearoff_adjustment->page_size >
@@ -3009,6 +3004,178 @@ gtk_menu_show (GtkWidget *widget)
   GTK_WIDGET_CLASS (gtk_menu_parent_class)->show (widget);
 }
 
+
+
+static void 
+gtk_menu_size_request_init (GtkSizeRequestIface *iface)
+{
+  iface->get_width            = gtk_menu_get_width;
+  iface->get_height           = gtk_menu_get_height;
+  iface->get_height_for_width = gtk_menu_get_height_for_width;
+}
+
+static void 
+gtk_menu_get_width (GtkSizeRequest      *widget,
+                   gint                *minimum_size,
+                   gint                *natural_size)
+{
+  GtkMenu        *menu;
+  GtkMenuShell   *menu_shell;
+  GtkMenuPrivate *priv;
+  GtkWidget      *child;
+  GList          *children;
+  guint           max_toggle_size;
+  guint           max_accel_width;
+  guint           horizontal_padding;
+  guint           border_width;
+  gint            child_min, child_nat;
+  gint            min_width, nat_width;
+
+  menu       = GTK_MENU (widget);
+  menu_shell = GTK_MENU_SHELL (widget);
+  priv       = gtk_menu_get_private (menu);
+  
+  min_width = nat_width = 0;
+  
+  max_toggle_size = 0;
+  max_accel_width = 0;
+  
+  children = menu_shell->children;
+  while (children)
+    {
+      gint part;
+      gint toggle_size;
+      gint l, r, t, b;
+
+      child = children->data;
+      children = children->next;
+      
+      if (! gtk_widget_get_visible (child))
+        continue;
+
+      get_effective_child_attach (child, &l, &r, &t, &b);
+
+      /* It's important to size_request the child
+       * before doing the toggle size request, in
+       * case the toggle size request depends on the size
+       * request of a child of the child (e.g. for ImageMenuItem)
+       */
+
+       GTK_MENU_ITEM (child)->show_submenu_indicator = TRUE;
+       gtk_size_request_get_width (GTK_SIZE_REQUEST (child), &child_min, &child_nat);
+
+       gtk_menu_item_toggle_size_request (GTK_MENU_ITEM (child), &toggle_size);
+       max_toggle_size = MAX (max_toggle_size, toggle_size);
+       max_accel_width = MAX (max_accel_width,
+                              GTK_MENU_ITEM (child)->accelerator_width);
+
+       part = child_min / (r - l);
+       min_width = MAX (min_width, part);
+
+       part = child_nat / (r - l);
+       nat_width = MAX (nat_width, part);
+    }
+
+  /* If the menu doesn't include any images or check items
+   * reserve the space so that all menus are consistent.
+   * We only do this for 'ordinary' menus, not for combobox
+   * menus or multi-column menus
+   */
+  if (max_toggle_size == 0 && 
+      gtk_menu_get_n_columns (menu) == 1 &&
+      !priv->no_toggle_size)
+    {
+      guint toggle_spacing;
+      guint indicator_size;
+
+      gtk_style_get (GTK_WIDGET (widget)->style,
+                     GTK_TYPE_CHECK_MENU_ITEM,
+                     "toggle-spacing", &toggle_spacing,
+                     "indicator-size", &indicator_size,
+                     NULL);
+
+      max_toggle_size = indicator_size + toggle_spacing;
+    }
+
+  min_width += 2 * max_toggle_size + max_accel_width;
+  min_width *= gtk_menu_get_n_columns (menu);
+
+  nat_width += 2 * max_toggle_size + max_accel_width;
+  nat_width *= gtk_menu_get_n_columns (menu);
+
+  gtk_widget_style_get (GTK_WIDGET (menu),
+                        "horizontal-padding", &horizontal_padding,
+                       NULL);
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (menu));
+  min_width   += (border_width + horizontal_padding + GTK_WIDGET (widget)->style->xthickness) * 2;
+  nat_width   += (border_width + horizontal_padding + GTK_WIDGET (widget)->style->xthickness) * 2;
+  
+  menu->toggle_size = max_toggle_size;
+  priv->accel_size  = max_accel_width;
+
+  if (minimum_size)
+    *minimum_size = min_width;
+
+  if (natural_size)
+    *natural_size = nat_width;
+
+  /* Don't resize the tearoff if it is not active, because it won't redraw (it is only a background pixmap).
+   */
+  if (menu->tearoff_active)
+    gtk_menu_set_tearoff_hints (menu, min_width);
+}
+
+static void 
+gtk_menu_get_height (GtkSizeRequest      *widget,
+                    gint                *minimum_size,
+                    gint                *natural_size)
+{
+  gint min_width;
+
+  /* Menus are height-for-width only, just return the height for the minimum width */
+  gtk_size_request_get_width (widget, &min_width, NULL);
+  gtk_size_request_get_height_for_width (widget, min_width, minimum_size, natural_size);
+}
+
+static void
+gtk_menu_get_height_for_width (GtkSizeRequest      *widget,
+                              gint                 for_size,
+                              gint                *minimum_size,
+                              gint                *natural_size)
+{
+  GtkMenu  *menu = GTK_MENU (widget);
+  guint    *min_heights, *nat_heights;
+  guint     vertical_padding, border_width;
+  gint      n_heights, i;
+  gint      min_height, nat_height;
+
+  gtk_widget_style_get (GTK_WIDGET (menu), "vertical-padding", &vertical_padding, NULL);
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (menu));
+
+  min_height = nat_height = (border_width + vertical_padding + GTK_WIDGET (widget)->style->ythickness) * 2;
+
+  n_heights = 
+    calculate_line_heights (menu, for_size, &min_heights, &nat_heights);
+
+  for (i = 0; i < n_heights; i++)
+    {
+      min_height += min_heights[i];
+      nat_height += nat_heights[i];
+    }
+
+  if (minimum_size)
+    *minimum_size = min_height;
+
+  if (natural_size)
+    *natural_size = nat_height;
+
+  g_free (min_heights);
+  g_free (nat_heights);
+}
+
+
+
 static gboolean
 gtk_menu_button_scroll (GtkMenu        *menu,
                         GdkEventButton *event)
@@ -3471,9 +3638,11 @@ gtk_menu_scroll_by (GtkMenu *menu,
   gint view_width, view_height;
   gboolean double_arrows;
   GtkBorder arrow_border;
+  GtkMenuPrivate *priv;
   
   widget = GTK_WIDGET (menu);
   offset = menu->scroll_offset + step;
+  priv   = gtk_menu_get_private (menu);
 
   get_arrows_border (menu, &arrow_border);
 
@@ -3495,7 +3664,7 @@ gtk_menu_scroll_by (GtkMenu *menu,
   gdk_drawable_get_size (widget->window, &view_width, &view_height);
 
   if (menu->scroll_offset == 0 &&
-      view_height >= widget->requisition.height)
+      view_height >= priv->requested_height)
     return;
 
   /* Don't scroll past the bottom if we weren't before: */
@@ -3508,9 +3677,9 @@ gtk_menu_scroll_by (GtkMenu *menu,
   if (double_arrows)
     view_height -= arrow_border.bottom;
 
-  if ((menu->scroll_offset + view_height <= widget->requisition.height) &&
-      (offset + view_height > widget->requisition.height))
-    offset = widget->requisition.height - view_height;
+  if ((menu->scroll_offset + view_height <= priv->requested_height) &&
+      (offset + view_height > priv->requested_height))
+    offset = priv->requested_height - view_height;
 
   if (offset != menu->scroll_offset)
     gtk_menu_scroll_to (menu, offset);
@@ -4308,12 +4477,10 @@ gtk_menu_position (GtkMenu *menu)
   gdk_display_get_device_state (gdk_screen_get_display (screen),
                                 pointer, &pointer_screen, &x, &y, NULL);
 
-  /* We need the requisition to figure out the right place to
-   * popup the menu. In fact, we always need to ask here, since
-   * if a size_request was queued while we weren't popped up,
-   * the requisition won't have been recomputed yet.
+  /* Get the minimum height for minimum width to figure out 
+   * the right place to popup the menu. 
    */
-  gtk_widget_size_request (widget, &requisition);
+  gtk_size_request_get_size (GTK_SIZE_REQUEST (widget), &requisition, NULL);
 
   if (pointer_screen != screen)
     {
@@ -4467,7 +4634,7 @@ gtk_menu_position (GtkMenu *menu)
 
   if (private->initially_pushed_in)
     {
-      menu_height = GTK_WIDGET (menu)->requisition.height;
+      menu_height = requisition.height;
 
       if (y + menu_height > monitor.y + monitor.height)
        {
@@ -4563,8 +4730,10 @@ gtk_menu_scroll_to (GtkMenu *menu,
   guint horizontal_padding;
   gboolean double_arrows;
   GtkBorder arrow_border;
+  GtkMenuPrivate *priv;
   
   widget = GTK_WIDGET (menu);
+  priv   = gtk_menu_get_private (menu);
 
   if (menu->tearoff_active &&
       menu->tearoff_adjustment &&
@@ -4590,7 +4759,7 @@ gtk_menu_scroll_to (GtkMenu *menu,
   border_width = gtk_container_get_border_width (GTK_CONTAINER (menu));
   view_width -= (border_width + widget->style->xthickness + horizontal_padding) * 2;
   view_height -= (border_width + widget->style->ythickness + vertical_padding) * 2;
-  menu_height = widget->requisition.height -
+  menu_height = priv->requested_height -
     (border_width + widget->style->ythickness + vertical_padding) * 2;
 
   x = border_width + widget->style->xthickness + horizontal_padding;
@@ -5244,8 +5413,11 @@ get_menu_height (GtkMenu *menu)
 {
   gint height;
   GtkWidget *widget = GTK_WIDGET (menu);
+  GtkAllocation allocation;
+
+  gtk_widget_get_allocation (widget, &allocation);
 
-  height = widget->requisition.height;
+  height = allocation.height;
   height -= gtk_container_get_border_width (GTK_CONTAINER (widget) + widget->style->ythickness) * 2;
 
   if (!menu->tearoff_active)
index ded538c26cf4f0c19b8b63349e55c612c1936f62..10c83bc9460a8b11108bc3fd37895c6c1dd69f9b 100644 (file)
@@ -38,6 +38,7 @@
 #include "gtkprivate.h"
 #include "gtkbuildable.h"
 #include "gtkactivatable.h"
+#include "gtksizerequest.h"
 #include "gtkintl.h"
 
 
@@ -78,8 +79,6 @@ static void gtk_menu_item_get_property   (GObject          *object,
                                          GValue           *value,
                                          GParamSpec       *pspec);
 static void gtk_menu_item_destroy        (GtkObject        *object);
-static void gtk_menu_item_size_request   (GtkWidget        *widget,
-                                         GtkRequisition   *requisition);
 static void gtk_menu_item_size_allocate  (GtkWidget        *widget,
                                          GtkAllocation    *allocation);
 static void gtk_menu_item_realize        (GtkWidget        *widget);
@@ -125,6 +124,17 @@ static void gtk_real_menu_item_set_label (GtkMenuItem     *menu_item,
                                          const gchar     *label);
 static G_CONST_RETURN gchar * gtk_real_menu_item_get_label (GtkMenuItem *menu_item);
 
+static void gtk_menu_item_size_request_init          (GtkSizeRequestIface *iface);
+static void gtk_menu_item_get_width                  (GtkSizeRequest      *widget,
+                                                     gint                *minimum_size,
+                                                     gint                *natural_size);
+static void gtk_menu_item_get_height                 (GtkSizeRequest      *widget,
+                                                     gint                *minimum_size,
+                                                     gint                *natural_size);
+static void gtk_menu_item_get_height_for_width       (GtkSizeRequest      *widget,
+                                                     gint                 for_size,
+                                                     gint                *minimum_size,
+                                                     gint                *natural_size);
 
 static void gtk_menu_item_buildable_interface_init (GtkBuildableIface   *iface);
 static void gtk_menu_item_buildable_add_child      (GtkBuildable        *buildable,
@@ -157,7 +167,9 @@ G_DEFINE_TYPE_WITH_CODE (GtkMenuItem, gtk_menu_item, GTK_TYPE_ITEM,
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                gtk_menu_item_buildable_interface_init)
                         G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
-                                               gtk_menu_item_activatable_interface_init))
+                                               gtk_menu_item_activatable_interface_init)
+                        G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST,
+                                               gtk_menu_item_size_request_init))
 
 #define GET_PRIVATE(object)  \
   (G_TYPE_INSTANCE_GET_PRIVATE ((object), GTK_TYPE_MENU_ITEM, GtkMenuItemPrivate))
@@ -177,7 +189,6 @@ gtk_menu_item_class_init (GtkMenuItemClass *klass)
 
   object_class->destroy = gtk_menu_item_destroy;
 
-  widget_class->size_request = gtk_menu_item_size_request;
   widget_class->size_allocate = gtk_menu_item_size_allocate;
   widget_class->expose_event = gtk_menu_item_expose;
   widget_class->realize = gtk_menu_item_realize;
@@ -557,6 +568,384 @@ gtk_menu_item_detacher (GtkWidget *widget,
   menu_item->submenu = NULL;
 }
 
+static void
+get_arrow_size (GtkWidget *widget,
+               GtkWidget *child,
+               gint      *size)
+{
+  PangoContext     *context;
+  PangoFontMetrics *metrics;
+  gfloat            arrow_scaling;
+         
+  g_assert (size);
+
+  gtk_widget_style_get (widget,
+                       "arrow-scaling", &arrow_scaling,
+                       NULL);
+         
+  context = gtk_widget_get_pango_context (child);
+  metrics = pango_context_get_metrics (context, 
+                                      child->style->font_desc,
+                                      pango_context_get_language (context));
+  
+  *size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
+                        pango_font_metrics_get_descent (metrics)));
+  
+  pango_font_metrics_unref (metrics);
+  
+  *size = *size * arrow_scaling;
+}
+
+
+static void
+gtk_menu_item_accel_width_foreach (GtkWidget *widget,
+                                  gpointer data)
+{
+  guint *width = data;
+
+  if (GTK_IS_ACCEL_LABEL (widget))
+    {
+      guint w;
+
+      w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
+      *width = MAX (*width, w);
+    }
+  else if (GTK_IS_CONTAINER (widget))
+    gtk_container_foreach (GTK_CONTAINER (widget),
+                          gtk_menu_item_accel_width_foreach,
+                          data);
+}
+
+static gint
+get_minimum_width (GtkWidget *widget)
+{
+  PangoContext *context;
+  PangoFontMetrics *metrics;
+  gint width;
+  gint width_chars;
+
+  context = gtk_widget_get_pango_context (widget);
+  metrics = pango_context_get_metrics (context,
+                                      widget->style->font_desc,
+                                      pango_context_get_language (context));
+
+  width = pango_font_metrics_get_approximate_char_width (metrics);
+
+  pango_font_metrics_unref (metrics);
+
+  gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
+
+  return PANGO_PIXELS (width_chars * width);
+}
+
+static void 
+gtk_menu_item_size_request_init (GtkSizeRequestIface *iface)
+{
+  iface->get_width            = gtk_menu_item_get_width;
+  iface->get_height           = gtk_menu_item_get_height;
+  iface->get_height_for_width = gtk_menu_item_get_height_for_width;
+}
+
+static void 
+gtk_menu_item_get_width (GtkSizeRequest      *request,
+                        gint                *minimum_size,
+                        gint                *natural_size)
+{
+  GtkMenuItem *menu_item;
+  GtkBin *bin;
+  GtkWidget *child, *widget = GTK_WIDGET (request);
+  guint accel_width;
+  guint horizontal_padding;
+  guint border_width;
+  GtkPackDirection pack_dir;
+  GtkPackDirection child_pack_dir;
+  gint  min_width, nat_width;
+
+  min_width = nat_width = 0;
+
+  gtk_widget_style_get (widget,
+                       "horizontal-padding", &horizontal_padding,
+                       NULL);
+  
+  bin = GTK_BIN (widget);
+  menu_item = GTK_MENU_ITEM (widget);
+
+  if (GTK_IS_MENU_BAR (widget->parent))
+    {
+      pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
+      child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
+    }
+  else
+    {
+      pack_dir = GTK_PACK_DIRECTION_LTR;
+      child_pack_dir = GTK_PACK_DIRECTION_LTR;
+    }
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+
+  min_width = (border_width + widget->style->xthickness) * 2;
+
+  if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
+      (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
+    min_width += 2 * horizontal_padding;
+
+  nat_width = min_width;
+
+  child = gtk_bin_get_child (bin);
+
+  if (child != NULL && gtk_widget_get_visible (child))
+    {
+      gint child_min, child_nat;
+
+      gtk_size_request_get_width (GTK_SIZE_REQUEST (child), &child_min, &child_nat);
+
+      if (menu_item->submenu && menu_item->show_submenu_indicator)
+       {
+         guint arrow_spacing;
+         gint  arrow_size;
+         
+         gtk_widget_style_get (widget,
+                               "arrow-spacing", &arrow_spacing,
+                               NULL);
+
+         get_arrow_size (widget, child, &arrow_size);
+
+         min_width += arrow_size;
+         min_width += arrow_spacing;
+
+         min_width = MAX (min_width, get_minimum_width (widget));
+
+         nat_width = min_width;
+       }
+
+
+      min_width += child_min;
+      nat_width += child_nat;
+
+
+    }
+
+  accel_width = 0;
+  gtk_container_foreach (GTK_CONTAINER (menu_item),
+                        gtk_menu_item_accel_width_foreach,
+                        &accel_width);
+  menu_item->accelerator_width = accel_width;
+
+  if (minimum_size)
+    *minimum_size = min_width;
+
+  if (natural_size)
+    *natural_size = nat_width;
+}
+
+static void 
+gtk_menu_item_get_height (GtkSizeRequest      *request,
+                         gint                *minimum_size,
+                         gint                *natural_size)
+{
+  GtkMenuItem *menu_item;
+  GtkBin *bin;
+  GtkWidget *child, *widget = GTK_WIDGET (request);
+  guint accel_width;
+  guint horizontal_padding;
+  guint border_width;
+  GtkPackDirection pack_dir;
+  GtkPackDirection child_pack_dir;
+  gint  min_height, nat_height;
+
+  min_height = nat_height = 0;
+
+  gtk_widget_style_get (widget,
+                       "horizontal-padding", &horizontal_padding,
+                       NULL);
+  
+  bin = GTK_BIN (widget);
+  menu_item = GTK_MENU_ITEM (widget);
+
+  if (GTK_IS_MENU_BAR (widget->parent))
+    {
+      pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
+      child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
+    }
+  else
+    {
+      pack_dir = GTK_PACK_DIRECTION_LTR;
+      child_pack_dir = GTK_PACK_DIRECTION_LTR;
+    }
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+  min_height = (border_width + widget->style->ythickness) * 2;
+
+  if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
+      (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
+    min_height += 2 * horizontal_padding;
+
+  nat_height = min_height;
+
+  child = gtk_bin_get_child (bin);
+
+  if (child != NULL && gtk_widget_get_visible (child))
+    {
+      gint child_min, child_nat;
+      
+      gtk_size_request_get_height (GTK_SIZE_REQUEST (child), &child_min, &child_nat);
+
+      min_height += child_min;
+      nat_height += child_nat;
+
+      if (menu_item->submenu && menu_item->show_submenu_indicator)
+       {
+         gint  arrow_size;
+
+         get_arrow_size (widget, child, &arrow_size);
+
+         min_height = MAX (min_height, arrow_size);
+         nat_height = MAX (nat_height, arrow_size);
+       }
+    }
+  else /* separator item */
+    {
+      gboolean wide_separators;
+      gint     separator_height;
+
+      gtk_widget_style_get (widget,
+                            "wide-separators",  &wide_separators,
+                            "separator-height", &separator_height,
+                            NULL);
+
+      if (wide_separators)
+        min_height += separator_height + widget->style->ythickness;
+      else
+        min_height += widget->style->ythickness * 2;
+
+      nat_height = min_height;
+    }
+
+  accel_width = 0;
+  gtk_container_foreach (GTK_CONTAINER (menu_item),
+                        gtk_menu_item_accel_width_foreach,
+                        &accel_width);
+  menu_item->accelerator_width = accel_width;
+
+  if (minimum_size)
+    *minimum_size = min_height;
+
+  if (natural_size)
+    *natural_size = nat_height;
+}
+
+static void
+gtk_menu_item_get_height_for_width (GtkSizeRequest      *request,
+                                   gint                 for_size,
+                                   gint                *minimum_size,
+                                   gint                *natural_size)
+{
+  GtkMenuItem *menu_item;
+  GtkBin *bin;
+  GtkWidget *child, *widget = GTK_WIDGET (request);
+  guint horizontal_padding;
+  guint border_width;
+  GtkPackDirection pack_dir;
+  GtkPackDirection child_pack_dir;
+  gint  min_height, nat_height;
+  gint  avail_size;
+
+  min_height = nat_height = 0;
+
+  gtk_widget_style_get (widget,
+                       "horizontal-padding", &horizontal_padding,
+                       NULL);
+  
+  bin = GTK_BIN (widget);
+  menu_item = GTK_MENU_ITEM (widget);
+
+  if (GTK_IS_MENU_BAR (widget->parent))
+    {
+      pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
+      child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
+    }
+  else
+    {
+      pack_dir = GTK_PACK_DIRECTION_LTR;
+      child_pack_dir = GTK_PACK_DIRECTION_LTR;
+    }
+
+  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+  min_height   = (border_width + widget->style->ythickness) * 2;
+
+  avail_size   = for_size;
+  avail_size  -= (border_width + widget->style->xthickness) * 2;
+
+  if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
+      (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
+    min_height += 2 * horizontal_padding;
+
+  if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
+      (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
+    avail_size -= 2 * horizontal_padding;
+
+  nat_height = min_height;
+
+  child = gtk_bin_get_child (bin);
+
+  if (child != NULL && gtk_widget_get_visible (child))
+    {
+      gint child_min, child_nat;
+      gint arrow_size = 0;
+      
+      if (menu_item->submenu && menu_item->show_submenu_indicator)
+       {
+
+         guint arrow_spacing;
+         
+         gtk_widget_style_get (widget,
+                               "arrow-spacing", &arrow_spacing,
+                               NULL);
+
+         get_arrow_size (widget, child, &arrow_size);
+
+         avail_size -= arrow_size;
+         avail_size -= arrow_spacing;
+       }
+
+      gtk_size_request_get_height_for_width (GTK_SIZE_REQUEST (child), avail_size, &child_min, &child_nat);
+
+      min_height += child_min;
+      nat_height += child_nat;
+
+      if (menu_item->submenu && menu_item->show_submenu_indicator)
+       {
+         min_height = MAX (min_height, arrow_size);
+         nat_height = MAX (nat_height, arrow_size);
+       }
+    }
+  else /* separator item */
+    {
+      gboolean wide_separators;
+      gint     separator_height;
+
+      gtk_widget_style_get (widget,
+                            "wide-separators",  &wide_separators,
+                            "separator-height", &separator_height,
+                            NULL);
+
+      if (wide_separators)
+        min_height += separator_height + widget->style->ythickness;
+      else
+        min_height += widget->style->ythickness * 2;
+
+      nat_height = min_height;
+    }
+
+  if (minimum_size)
+    *minimum_size = min_height;
+
+  if (natural_size)
+    *natural_size = nat_height;
+}
+
+
+
 static void
 gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface)
 {
@@ -886,140 +1275,6 @@ gtk_menu_item_toggle_size_allocate (GtkMenuItem *menu_item,
   g_signal_emit (menu_item, menu_item_signals[TOGGLE_SIZE_ALLOCATE], 0, allocation);
 }
 
-static void
-gtk_menu_item_accel_width_foreach (GtkWidget *widget,
-                                  gpointer data)
-{
-  guint *width = data;
-
-  if (GTK_IS_ACCEL_LABEL (widget))
-    {
-      guint w;
-
-      w = gtk_accel_label_get_accel_width (GTK_ACCEL_LABEL (widget));
-      *width = MAX (*width, w);
-    }
-  else if (GTK_IS_CONTAINER (widget))
-    gtk_container_foreach (GTK_CONTAINER (widget),
-                          gtk_menu_item_accel_width_foreach,
-                          data);
-}
-
-static gint
-get_minimum_width (GtkWidget *widget)
-{
-  PangoContext *context;
-  PangoFontMetrics *metrics;
-  gint width;
-  gint width_chars;
-
-  context = gtk_widget_get_pango_context (widget);
-  metrics = pango_context_get_metrics (context,
-                                      widget->style->font_desc,
-                                      pango_context_get_language (context));
-
-  width = pango_font_metrics_get_approximate_char_width (metrics);
-
-  pango_font_metrics_unref (metrics);
-
-  gtk_widget_style_get (widget, "width-chars", &width_chars, NULL);
-
-  return PANGO_PIXELS (width_chars * width);
-}
-
-static void
-gtk_menu_item_size_request (GtkWidget      *widget,
-                           GtkRequisition *requisition)
-{
-  GtkMenuItem *menu_item;
-  GtkBin *bin;
-  GtkWidget *child;
-  guint accel_width;
-  guint horizontal_padding;
-  guint border_width;
-  GtkPackDirection pack_dir;
-  GtkPackDirection child_pack_dir;
-
-  g_return_if_fail (GTK_IS_MENU_ITEM (widget));
-  g_return_if_fail (requisition != NULL);
-
-  gtk_widget_style_get (widget,
-                       "horizontal-padding", &horizontal_padding,
-                       NULL);
-  
-  bin = GTK_BIN (widget);
-  menu_item = GTK_MENU_ITEM (widget);
-
-  if (GTK_IS_MENU_BAR (widget->parent))
-    {
-      pack_dir = gtk_menu_bar_get_pack_direction (GTK_MENU_BAR (widget->parent));
-      child_pack_dir = gtk_menu_bar_get_child_pack_direction (GTK_MENU_BAR (widget->parent));
-    }
-  else
-    {
-      pack_dir = GTK_PACK_DIRECTION_LTR;
-      child_pack_dir = GTK_PACK_DIRECTION_LTR;
-    }
-
-  border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-  requisition->width = (border_width + widget->style->xthickness) * 2;
-  requisition->height = (border_width + widget->style->ythickness) * 2;
-
-  if ((pack_dir == GTK_PACK_DIRECTION_LTR || pack_dir == GTK_PACK_DIRECTION_RTL) &&
-      (child_pack_dir == GTK_PACK_DIRECTION_LTR || child_pack_dir == GTK_PACK_DIRECTION_RTL))
-    requisition->width += 2 * horizontal_padding;
-  else if ((pack_dir == GTK_PACK_DIRECTION_TTB || pack_dir == GTK_PACK_DIRECTION_BTT) &&
-      (child_pack_dir == GTK_PACK_DIRECTION_TTB || child_pack_dir == GTK_PACK_DIRECTION_BTT))
-    requisition->height += 2 * horizontal_padding;
-
-  child = gtk_bin_get_child (bin);
-
-  if (child != NULL && gtk_widget_get_visible (child))
-    {
-      GtkRequisition child_requisition;
-      
-      gtk_widget_size_request (child, &child_requisition);
-
-      requisition->width += child_requisition.width;
-      requisition->height += child_requisition.height;
-
-      if (menu_item->submenu && menu_item->show_submenu_indicator)
-       {
-         guint arrow_spacing;
-         
-         gtk_widget_style_get (widget,
-                               "arrow-spacing", &arrow_spacing,
-                               NULL);
-
-         requisition->width += child_requisition.height;
-         requisition->width += arrow_spacing;
-
-         requisition->width = MAX (requisition->width, get_minimum_width (widget));
-       }
-    }
-  else /* separator item */
-    {
-      gboolean wide_separators;
-      gint     separator_height;
-
-      gtk_widget_style_get (widget,
-                            "wide-separators",  &wide_separators,
-                            "separator-height", &separator_height,
-                            NULL);
-
-      if (wide_separators)
-        requisition->height += separator_height + widget->style->ythickness;
-      else
-        requisition->height += widget->style->ythickness * 2;
-    }
-
-  accel_width = 0;
-  gtk_container_foreach (GTK_CONTAINER (menu_item),
-                        gtk_menu_item_accel_width_foreach,
-                        &accel_width);
-  menu_item->accelerator_width = accel_width;
-}
-
 static void
 gtk_menu_item_size_allocate (GtkWidget     *widget,
                             GtkAllocation *allocation)
@@ -1224,32 +1479,17 @@ gtk_menu_item_paint (GtkWidget    *widget,
        {
          gint arrow_x, arrow_y;
          gint arrow_size;
-         gint arrow_extent;
          guint horizontal_padding;
-          gfloat arrow_scaling;
          GtkTextDirection direction;
          GtkArrowType arrow_type;
-         PangoContext *context;
-         PangoFontMetrics *metrics;
 
          direction = gtk_widget_get_direction (widget);
       
          gtk_widget_style_get (widget,
                                "horizontal-padding", &horizontal_padding,
-                                "arrow-scaling", &arrow_scaling,
                                NULL);
-         
-         context = gtk_widget_get_pango_context (child);
-         metrics = pango_context_get_metrics (context, 
-                                              child->style->font_desc,
-                                              pango_context_get_language (context));
-
-         arrow_size = (PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
-                                      pango_font_metrics_get_descent (metrics)));
-
-         pango_font_metrics_unref (metrics);
 
-         arrow_extent = arrow_size * arrow_scaling;
+         get_arrow_size (widget, child, &arrow_size);
 
          shadow_type = GTK_SHADOW_OUT;
          if (state_type == GTK_STATE_PRELIGHT)
@@ -1257,7 +1497,7 @@ gtk_menu_item_paint (GtkWidget    *widget,
 
          if (direction == GTK_TEXT_DIR_LTR)
            {
-             arrow_x = x + width - horizontal_padding - arrow_extent;
+             arrow_x = x + width - horizontal_padding - arrow_size;
              arrow_type = GTK_ARROW_RIGHT;
            }
          else
@@ -1266,14 +1506,14 @@ gtk_menu_item_paint (GtkWidget    *widget,
              arrow_type = GTK_ARROW_LEFT;
            }
 
-         arrow_y = y + (height - arrow_extent) / 2;
+         arrow_y = y + (height - arrow_size) / 2;
 
          gtk_paint_arrow (widget->style, widget->window,
                           state_type, shadow_type, 
                           area, widget, "menuitem", 
                           arrow_type, TRUE,
                           arrow_x, arrow_y,
-                          arrow_extent, arrow_extent);
+                          arrow_size, arrow_size);
        }
       else if (!child)
        {